package dletc.lock;
//模拟银行取钱，多线程会导致错误数据
public class unsafeBank {

    public static void main(String[] args) {
        Account a = new Account("A账户", 100);
        bankBusiness tutu = new bankBusiness(a, 50);
        bankBusiness meimei = new bankBusiness(a, 100);
        tutu.setName("tutu");
        meimei.setName("meimei");
        tutu.start();
        meimei.start();
    }

}

class Account{

    private String name;  //账号名称
    private double money; //账号余额

    public Account(String name, double money) {
        this.name = name;
        this.money = money;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

//银行业务操作 模拟取钱
class bankBusiness extends Thread{

    private Account account; //账户信息

    private double amount; //取款金额

    public bankBusiness(Account account,double amount){
        this.account = account;
        this.amount = amount;
    }

    @Override
    public void run() {
        //取钱
        try {
            drawMoney(amount);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //添加synchronized关键字 不能实现线程同步 因为synchronized锁的是this 这里new了两个对象 所以锁不住。
    //所以使用 synchronized 代码块 自定义锁 锁同步数据
    private void drawMoney(double amount) throws InterruptedException {
        //账户余额小于0时，不能取钱
        synchronized (account){
            if(account.getMoney() - amount < 0){
                System.out.println("账户余额不足，不能提取：" + amount);
                return;
            }
            Thread.sleep(100);
            //this.getName() == Thread.currentThread.getName() 因为继承了Thread类 具有getName方法
            System.out.println(this.getName() + "取了"+ amount +"钱");
            account.setMoney(account.getMoney() - amount); //取完钱重新赋值余额
            System.out.println(account.getName() + "余额为：" + account.getMoney() );
        }

    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }
}
